{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "3a8d3ccf-fc3e-406d-a3de-50b8a6ea3459",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DatasetDict({\n",
      "    train: Dataset({\n",
      "        features: ['content', 'summary'],\n",
      "        num_rows: 114599\n",
      "    })\n",
      "    validation: Dataset({\n",
      "        features: ['content', 'summary'],\n",
      "        num_rows: 1070\n",
      "    })\n",
      "})\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>content</th>\n",
       "      <th>summary</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>类型#上衣*颜色#纯色*图案#纯色*图案#撞色*衣样式#风衣*衣款式#拼接</td>\n",
       "      <td>风衣是女性衣橱里必不可少的单品呢，这款更是如此，长款的设计，尽显高挑身材。撞色拼接设计，青春活力十足，适合各种年龄段的女性。纯色系主打，更是增添女性优雅BRAND的魅力，品质面料，穿上挺括有型，自带女王气场，让你整个春天都美丽动人。</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>类型#裙*版型#宽松*版型#显瘦*材质#牛仔布*颜色#黑色*风格#简约*风格#休闲*裙型#牛仔裙</td>\n",
       "      <td>黑色存在的本身，就是诉说着简约质感的存在，虽然黑色是显瘦的存在，但是这里的宽松裤型，则是使它呈现出了休闲的腔调，&lt;UNK&gt;黑色，无疑是更加百搭且深邃的模样。牛仔的加注，与生俱来的经典视感，那经过时间洗礼所显现出的简约质感，一气呵成！</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>类型#上衣*材质#针织*风格#性感*图案#条纹*衣样式#针织衫*衣领型#v领*衣款式#吊带*衣款式#露肩</td>\n",
       "      <td>吊带和v领结合在一起使得这款针织衫上身达到一种性感露肩的效果，凸显得气质优雅迷人，露出精致锁骨，超级吸睛啊有没有。坑条纹针织面料手感细腻，上身很显立体感，衬托得身材更加丰满婀娜。前短后长衣摆凸显纤细腰身，拉长身形显腿长。</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>input_ids</th>\n",
       "      <th>labels</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[64790, 64792, 30910, 33467, 31010, 56778, 30998, 38317, 31010, 55148, 55790, 30998, 33692, 31010, 56154, 32658, 30998, 56778, 40877, 31010, 36378, 55037, 30910, 36422, 32863, 55115, 56553, 57439, 34481, 54538, 31123, 57494, 54878, 33894, 55487, 34667, 55148, 55790, 46839, 38317, 31123, 54548, 39080, 55215, 56244, 55640, 55035, 54892, 42721, 39362, 54530, 33481, 35772, 54659, 31002, 5234, 30984, 30994, 54902, 59300, 56089, 32492, 56154, 32658, 32985, 52124, 54530, 55148, 55790, 46839, 31123, 32425, 35400, 33894, 34794, 34063, 54659, 55087, 54642, 51100, 33069, 45369, 54578, 56164, 31123, 55487, 54666, 34317, 39232, 58643, 54530, 35642, 31155, 2]</td>\n",
       "      <td>[-100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, 30910, 36422, 32863, 55115, 56553, 57439, 34481, 54538, 31123, 57494, 54878, 33894, 55487, 34667, 55148, 55790, 46839, 38317, 31123, 54548, 39080, 55215, 56244, 55640, 55035, 54892, 42721, 39362, 54530, 33481, 35772, 54659, 31002, 5234, 30984, 30994, 54902, 59300, 56089, 32492, 56154, 32658, 32985, 52124, 54530, 55148, 55790, 46839, 31123, 32425, 35400, 33894, 34794, 34063, 54659, 55087, 54642, 51100, 33069, 45369, 54578, 56164, 31123, 55487, 54666, 34317, 39232, 58643, 54530, 35642, 31155, 2]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "759e1b993d65457ca9b23c82f6449c14",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "You are using an old version of the checkpointing format that is deprecated (We will also silently ignore `gradient_checkpointing_kwargs` in case you passed it).Please update to the new format on your modeling file. To use the new format, you need to completely remove the definition of the method `_set_gradient_checkpointing` in your model.\n",
      "You are using an old version of the checkpointing format that is deprecated (We will also silently ignore `gradient_checkpointing_kwargs` in case you passed it).Please update to the new format on your modeling file. To use the new format, you need to completely remove the definition of the method `_set_gradient_checkpointing` in your model.\n",
      "No label_names provided for model class `PeftModelForCausalLM`. Since `PeftModel` hides base models input arguments, if label_names is not given, label_names can't be set automatically within `Trainer`. Note that empty label_names list will be used instead.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3739.69MiB\n",
      "trainable params: 974,848 || all params: 6,244,558,848 || trainable%: 0.0156\n",
      "开始训练...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      \n",
       "      <progress value='100' max='100' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      [100/100 47:55, Epoch 0/1]\n",
       "    </div>\n",
       "    <table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       " <tr style=\"text-align: left;\">\n",
       "      <th>Step</th>\n",
       "      <th>Training Loss</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>10</td>\n",
       "      <td>4.669800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>20</td>\n",
       "      <td>3.800100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>30</td>\n",
       "      <td>3.610200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>40</td>\n",
       "      <td>3.515000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>50</td>\n",
       "      <td>3.447700</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>60</td>\n",
       "      <td>3.414400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>70</td>\n",
       "      <td>3.370600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>80</td>\n",
       "      <td>3.378600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>90</td>\n",
       "      <td>3.375000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>100</td>\n",
       "      <td>3.362300</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table><p>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n",
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n",
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n",
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型保存完成！\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1IAAAIoCAYAAABj6NoUAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjUsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvWftoOwAAAAlwSFlzAAAPYQAAD2EBqD+naQAArR5JREFUeJzs3Xl8E3X+P/DXJD2BttBytEChtCjlKCigKyACciryQ8V1RZRDdL+73q6uiisK6gp47Op6rxeItyygInJTFAUFFa0FylGwFSiVtrQFembm98eYtOmZvptkZtLX8/HIg+STSfL5vGYa+u7MfEbRNE0DERERERERecxmdAeIiIiIiIishoUUERERERFRE7GQIiIiIiIiaiIWUkRERERERE3EQoqIiIiIiKiJWEgRERERERE1EQspIiIiIiKiJmIhRURERERE1EQspIiIiIiIiJqIhRQREbkoioKRI0c26z1SU1OhKArmzZvnlT4RERGZEQspIiKTURSlSTdqXEJCAsLCwozuhlccOXIEc+bMwcCBA9G2bVuEhIQgLi4OEydOxOLFi1FeXm50F4mIWoQgoztARETuHn744VptzzzzDAoLC+t8zpv27NmDVq1aNes9zj//fOzZswft27f3Uq/I6b333sPs2bNRUlKCQYMG4brrrkNUVBRycnKwadMmzJo1C0uXLsXGjRuN7ioRUcBTNE3TjO4EERE1LCEhAb/88gv4lS2TkJCAnJwclJaWGt0VsTVr1mDixIlo27Yt3n//fYwdO9bteU3TsHLlSrz22mv47LPPDOolEVHLwUP7iIgs6vDhw1AUBTNnzsSePXtwxRVXICYmBoqi4PDhwwCAFStWYOrUqejZsydatWqFqKgoDB8+HP/73//qfM+6zpGaOXMmFEXBoUOH8J///AfJyckIDQ1F9+7dMX/+fKiq6rZ8fedIJSQkICEhAadOncIdd9yBzp07IzQ0FP3798eyZcvqHeOf/vQnREdHo02bNhgxYgS++OILzJs3D4qiIDU1VRJdg06fPo2HH34YycnJCAsLQ3R0NCZOnIivvvqq1rKlpaV4+umnMWDAAERFRaF169ZISEjA1VdfjR9//NG1nKqqeO2113D++ecjOjoa4eHh6Nq1KyZNmuTRGBwOB2655RaoqooPP/ywVhEF6OvuiiuuwPLly11tDeW0ePFiKIqCxYsXu9oa2qZ2796NiIgIJCUl1dvP/v37Izw8HEVFRa42TdPwxhtvYNiwYYiMjESrVq0wePBgvPHGG42Om4jIzHhoHxGRxR04cAAXXHABUlJSMHPmTOTl5SEkJAQAMGfOHISEhODCCy9EXFwcfvvtN3zyySe46qqr8J///Ae33Xabx5/z97//HVu2bMFll12G8ePHY+XKlZg3bx7Ky8vxz3/+06P3qKiowLhx41BQUIApU6bgzJkzeP/993H11VdjzZo1GDdunGvZI0eOYOjQoTh27BgmTJiAc889FxkZGRg7diwuvvjipoXkodLSUlx88cX49ttvMXDgQNx55504fvw4PvjgA6xduxbvvfce/vjHP7qWnzFjBj788EP0798fs2bNQmhoKLKzs7F582bs2LEDAwYMAKCvhyeeeAJJSUm49tprERERgSNHjmDr1q3YsGFDoxN8bN68GZmZmRg6dChGjx7d4LKhoaHNzqGubapt27aYMmUKlixZgq+//hpDhw51e82PP/6ItLQ0/OlPf0JkZCQAvYiaNm0a3nvvPZx11lm49tprERISgvXr12P27NnYvXs3nnrqqWb3l4jIEBoREZle9+7dtZpf2YcOHdIAaAC0hx56qM7XHTx4sFZbcXGxlpKSokVFRWmnT592ew6ANmLECLe2GTNmaAC0Hj16aEePHnW1//bbb1rbtm21iIgIrayszNW+efNmDYD28MMP1zmGyZMnuy2/YcMGDYA2fvx4t+Wvu+46DYD2z3/+06399ddfd4178+bNdY67pu7du2uhoaGNLjd//nwNgDZt2jRNVVVX+/fff6+FhIRobdu21YqKijRN07STJ09qiqJogwYN0iorK93ep7KyUisoKHA9jo6O1jp37lwrb03TtLy8vEb7NW/ePA2A9uCDDza6bHUPP/xwvTm9+eabGgDtzTffdLU1tk0519Vf//rXWs/dfffdGgBt1apVrrb//ve/GgBt1qxZWnl5uau9rKxMmzRpkgZA27lzZ5PGRERkFjy0j4jI4mJjY/GPf/yjzucSExNrtbVp0wYzZ85EYWEhduzY4fHnzJ07F3Fxca7H7du3x+TJk1FcXIyMjAyP3+ff//63a48ZAIwePRrdu3d360tZWRk++ugjdOzYEXfffbfb62fNmoVevXp5/HlNsWTJEgQHB2PhwoVuMyKee+65mDFjBk6ePImVK1cC0A+l0zQNYWFhsNnc/zu12+1o27atW1tISAjsdnutz4yOjm60Xzk5OQCArl27NnFEMvVtU6NGjUKXLl3w4YcfoqKiwtWuqireffdddOjQAePHj3e1P//882jdujVeeOEFBAcHu9pDQkJcezHfe+89H46EiMh3eGgfEZHFDRgwwK0wqS43NxcLFy7E559/jl9++QUlJSVuzx89etTjzxk0aFCtNucv9idPnvToPdq2bYsePXrU+T7btm1zPc7IyEBZWRkGDx5c61A1RVEwdOjQJhVvnigqKkJmZiZ69+5dZ8EyatQovPrqq9i1axeuv/56REZG4tJLL8Xq1asxcOBA/PGPf8TIkSNx3nnnuRUNAHDNNdfgxRdfRL9+/XDNNddg1KhRGDJkCMLDw706Bm+pb5uy2WyYNm0annjiCaxevRqTJ08GAGzcuBHHjh3DbbfdhqAg/VeLM2fOIC0tDZ07d8aiRYtqvZezENu7d68PR0JE5DsspIiILK5Tp051tufn5+O8885DVlYWhg0bhjFjxqBt27aw2+3YtWsXPv74Y5SVlXn8Oc7zXqpz/tLscDg8eo+oqKg624OCgtwmrXBOVtCxY8c6l69vzM3h/Mz63tu5N676RAofffQRHn/8cbz77ruuPTiRkZGYNWsWHn/8cddU8s8++yx69OiBN998E4899hgee+wxhIWF4eqrr8bTTz/d6FTxsbGxAPTzxvyhoXyvv/56PPHEE3j77bddhdTSpUtdzzkVFBRA0zQcOXIE8+fPr/f9Tp8+7aVeExH5Fw/tIyKyuPouyvv6668jKysLjz76KLZu3YrnnnsOjz76KObNm4cLLrjAz71sGmfRlpubW+fzx48f99ln1vfezsPrqheUrVq1wmOPPYbMzExkZmbi9ddfR69evfDss8/irrvuci0XFBSEe+65B+np6Thy5AjeffddDB8+HG+99RamTZvWaN+GDRsGAE2+PpTzkMPKyspazxUWFtb7uoYu9NyvXz+cc845WLVqFQoLC3HmzBmsWLECvXr1wnnnnedazpnToEGDoGlavbfNmzc3aUxERGbBQoqIKEAdPHgQAFx7Dar78ssv/d2dJunVqxdCQ0Px3Xff1dprpmma22GA3hIZGYnExEQcOHCgzj0/zinEzznnnDpf36NHD9xwww3YsmUL2rRpg08++aTO5Tp37oypU6dizZo16NmzJzZs2FDrkMuaRo0ahcTERHz99deNFh7V82rXrh2Auvdk/fDDDw2+T0Ouv/56lJaWYtmyZVixYgVOnTqF6667zm2ZiIgI9O7dG3v27PH40E8iIithIUVEFKC6d+8OANi6datb+7vvvovVq1cb0SWPhYaG4qqrrsLx48fxzDPPuD331ltv+ey8mhkzZqCiogJz5sxxu/jxTz/9hMWLFyMqKgqXX345AOC3337Dzz//XOs9CgoKUFZWhrCwMAB6YfP111/XWu706dM4deoUgoODa01WUZPdbscLL7wAm82Gq6++Gps2bapzuU8//RRXXXWV67FzD9Fbb73ldujktm3b8M477zT4mQ259tprYbfbsXTpUixduhSKotQqpADg9ttvx5kzZ3DTTTfVeQjfoUOHXNc8IyKyGp4jRUQUoK6//nosWrQIt912GzZv3ozu3bvjxx9/xMaNG3HllVe6XbjVjBYsWIANGzbg/vvvx5YtW1zXkVq1ahUmTJiANWvWNFqAVFdRUYGZM2fW+/zixYtx77334rPPPsPSpUuxZ88ejB49Grm5ufjggw9QWVmJV199FREREQD0vTznnnsuBgwYgP79+6NLly7Iy8vDxx9/jIqKCtxzzz0AgJKSEgwbNgxnn302Bg0ahG7duuHUqVNYtWoVcnJycM8993h07acJEyZg6dKluPHGGzF69GgMHjwYQ4YMQUREBI4fP47U1FQcPHgQY8aMcb3mggsuwLBhw7Bp0yYMGTIEF110EX755Rd8/PHHmDRpElasWOFxftXFxsZizJgxWLduHWw2Gy688EIkJCTUWu7//u//sH37dixZsgRfffUVxowZg86dO+P48ePYu3cvvvnmG7z77rt1vpaIyOxYSBERBaiuXbtiy5YtuPfee7FhwwZUVlZi4MCBWLduHbKzs01fSMXHx2Pbtm247777sG7dOmzZsgWDBg3CunXr8NFHHwGoewKM+qiqiiVLltT7/OLFixEWFoZNmzZh0aJF+OCDD/Dvf/8brVq1wogRI/DAAw/gwgsvdC2fkJCAefPmYdOmTdiwYQPy8vLQvn17DBw4EHfccQcmTJgAAGjdujUWLVqEjRs34ssvv0Rubi7atWuHXr16YcGCBbjmmms8HsO1116LESNG4LnnnsO6deuwZMkSnDlzBjExMTj33HPx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NY8vBdxn7/Pj94+l1JUbNY65yTA3OWYnw9xkmJuMx4XAyZPAlCl6oVTHZBZuVFVfbsoU/XV+kJCQgCFDhuC9995ztX3++ecoLCzENddc06T3uvrqq1FcXIwFCxbg6quvxuLFi+s8715SRC1evBhXX3017HY7FixYgJtuugnLly/HhRde6FasTJkyBStWrMCsWbPw4osv4vbbb0dxcTGysrIAALm5uRg3bhwOHz6M+++/H8899xymTZuG7du3u33enDlz0Lt371qFWn0qKytx4sQJHD16FOvWrcODDz6IiIgInH/++R69vry8HCdOnEB2djZWrFiBp556Ct27d0fPnj1dy2zatAnJyclYvXo1unbtioiICMTExGDu3Ll1TpRSk/M8xfbt23vUJ28w1WQTjcnKynI7DjM+Ph5r167FXXfdhf79+6NLly644447cN999xnYS9+YMAG46y79/po1wO+HiRIREREZZ8kS4MyZ2nuh6qOq+vJvvQXcfrtv+/a7a6+9FnPmzEFJSQnCw8PxzjvvYMSIEejcuXOT3ufcc8/F66+/7nqcl5eH119/HYsWLWpW/yoqKnDfffehX79++OKLL1znq1144YW47LLL8O9//xvz58/HyZMn8fXXX+PJJ5/EPffc43p99Z0MX3/9NQoKCrBu3ToMHjzY1d7YTNiN2blzJ4YMGeJ63KtXL3zyySeIjo726PXLly/H1KlTXY8HDx6MN954A0FBVaXIwYMHYbfbMWvWLNx7770YMGAAli9fjsceewyVlZVYsGBBve+fn5+P1157DcOHD0dcXJxghDKm2SNVl9TUVLeJJlJTU7F48WK3ZYYMGYLt27ejtLQUBw8exAMPPFDv1OdW1qsX4NyL+cUXwOnTxvaHiIiIWjhNA557Tvba//zH8+Krma6++mqUlJRg1apVKC4uxqpVq+o9rK8hzlkAnYYPH468vDzXpXSkdu7cidzcXNx8881uk35MnDgRycnJ+OyzzwDoM+OFhIQgNTXVbcbY6tq2bQtAn5ChocP2Fi9eDE3TXIfYNaZPnz5Yv349Vq5ciXvvvRetW7du0ux2o0aNwvr16/HRRx/hL3/5C4KDg3G6xi+zp06dQkFBAebPn49HHnkEU6ZMwTvvvIMJEybg2WefrXeyDlVVMW3aNJw8eRLPSbdHIVMXUi2RzWZDYmJirRlQFAWu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",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 在 AdvertiseGen 数据集10K examples上使用 QLoRA 微调 ChatGLM3-6B，观察 Loss 变化情况\n",
    "# 定义全局变量和参数\n",
    "model_name_or_path = 'THUDM/chatglm3-6b'  # 模型ID或本地路径\n",
    "train_data_path = 'HasturOfficial/adgen'    # 训练数据路径\n",
    "eval_data_path = None                     # 验证数据路径，如果没有则设置为None\n",
    "seed = 8                                 # 随机种子\n",
    "max_input_length = 512                    # 输入的最大长度\n",
    "max_output_length = 1536                  # 输出的最大长度\n",
    "lora_rank = 4                             # LoRA秩\n",
    "lora_alpha = 32                           # LoRA alpha值\n",
    "lora_dropout = 0.05                       # LoRA Dropout率\n",
    "resume_from_checkpoint = None             # 如果从checkpoint恢复训练，指定路径\n",
    "prompt_text = ''                          # 所有数据前的指令文本\n",
    "compute_dtype = 'fp32'                    # 计算数据类型（fp32, fp16, bf16）\n",
    "\n",
    "from datasets import load_dataset\n",
    "from datasets import ClassLabel, Sequence\n",
    "import random\n",
    "import pandas as pd\n",
    "from IPython.display import display, HTML\n",
    "import torch\n",
    "from typing import List, Dict, Optional\n",
    "from transformers import AutoTokenizer, AutoModel, BitsAndBytesConfig, TrainingArguments, Trainer\n",
    "from peft import TaskType, LoraConfig, get_peft_model, prepare_model_for_kbit_training\n",
    "from peft.utils import TRANSFORMERS_MODELS_TO_LORA_TARGET_MODULES_MAPPING\n",
    "target_modules = TRANSFORMERS_MODELS_TO_LORA_TARGET_MODULES_MAPPING['chatglm']\n",
    "\n",
    "dataset = load_dataset(train_data_path)\n",
    "print(dataset) # 打印数据集结果\n",
    "dataset[\"train\"] = dataset[\"train\"].select(range(10000)) # 训练集只取10K的数据去训练\n",
    "\n",
    "\n",
    "def show_random_elements(dataset, num_examples=10):\n",
    "    assert num_examples <= len(dataset), \"Can't pick more elements than there are in the dataset.\"\n",
    "    picks = []\n",
    "    for _ in range(num_examples):\n",
    "        pick = random.randint(0, len(dataset)-1)\n",
    "        while pick in picks:\n",
    "            pick = random.randint(0, len(dataset)-1)\n",
    "        picks.append(pick)\n",
    "    \n",
    "    df = pd.DataFrame(dataset[picks])\n",
    "    for column, typ in dataset.features.items():\n",
    "        if isinstance(typ, ClassLabel):\n",
    "            df[column] = df[column].transform(lambda i: typ.names[i])\n",
    "        elif isinstance(typ, Sequence) and isinstance(typ.feature, ClassLabel):\n",
    "            df[column] = df[column].transform(lambda x: [typ.feature.names[i] for i in x])\n",
    "    display(HTML(df.to_html()))\n",
    "\n",
    "\n",
    "show_random_elements(dataset[\"train\"], num_examples=3)\n",
    "\n",
    "\n",
    "\n",
    "# revision='b098244' 版本对应的 ChatGLM3-6B 设置 use_reentrant=False\n",
    "# 最新版本 use_reentrant 被设置为 True，会增加不必要的显存开销\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name_or_path,\n",
    "                                          trust_remote_code=True,\n",
    "                                          use_reentrant=False,  # 推荐设置\n",
    "                                          revision='b098244')\n",
    "\n",
    "# tokenize_func 函数\n",
    "def tokenize_func(example, tokenizer, ignore_label_id=-100):\n",
    "    \"\"\"\n",
    "    对单个数据样本进行tokenize处理。\n",
    "    参数:\n",
    "    example (dict): 包含'content'和'summary'键的字典，代表训练数据的一个样本。\n",
    "    tokenizer (transformers.PreTrainedTokenizer): 用于tokenize文本的tokenizer。\n",
    "    ignore_label_id (int, optional): 在label中用于填充的忽略ID，默认为-100。\n",
    "    返回:\n",
    "    dict: 包含'tokenized_input_ids'和'labels'的字典，用于模型训练。\n",
    "    \"\"\"\n",
    "    # 构建问题文本\n",
    "    question = prompt_text + example['content']\n",
    "    if example.get('input', None) and example['input'].strip():\n",
    "        question += f'\\n{example[\"input\"]}'\n",
    "\n",
    "    # 构建答案文本\n",
    "    answer = example['summary']\n",
    "\n",
    "    # 对问题和答案文本进行tokenize处理 - 使用更基础的方法避免padding问题\n",
    "    # 注意：这里我们直接使用tokenizer的convert_tokens_to_ids方法\n",
    "    q_tokens = tokenizer.tokenize(question)\n",
    "    a_tokens = tokenizer.tokenize(answer)\n",
    "    \n",
    "    # 转换为ID\n",
    "    q_ids = tokenizer.convert_tokens_to_ids(q_tokens)\n",
    "    a_ids = tokenizer.convert_tokens_to_ids(a_tokens)\n",
    "\n",
    "    # 如果tokenize后的长度超过最大长度限制，则进行截断\n",
    "    if len(q_ids) > max_input_length - 2:  # 保留空间给gmask和bos标记\n",
    "        q_ids = q_ids[:max_input_length - 2]\n",
    "    if len(a_ids) > max_output_length - 1:  # 保留空间给eos标记\n",
    "        a_ids = a_ids[:max_output_length - 1]\n",
    "\n",
    "    # 构建模型的输入格式\n",
    "    input_ids = tokenizer.build_inputs_with_special_tokens(q_ids, a_ids)\n",
    "    question_length = len(q_ids) + 2  # 加上gmask和bos标记\n",
    "\n",
    "    # 构建标签，对于问题部分的输入使用ignore_label_id进行填充\n",
    "    labels = [ignore_label_id] * question_length + input_ids[question_length:]\n",
    "\n",
    "    return {'input_ids': input_ids, 'labels': labels}\n",
    "\n",
    "column_names = dataset['train'].column_names\n",
    "tokenized_dataset = dataset['train'].map(\n",
    "    lambda example: tokenize_func(example, tokenizer),\n",
    "    batched=False, \n",
    "    remove_columns=column_names\n",
    ")\n",
    "\n",
    "\n",
    "show_random_elements(tokenized_dataset, num_examples=1)\n",
    "\n",
    "tokenized_dataset = tokenized_dataset.shuffle(seed=seed)\n",
    "tokenized_dataset = tokenized_dataset.flatten_indices()\n",
    "\n",
    "\n",
    "\n",
    "# DataCollatorForChatGLM 类\n",
    "class DataCollatorForChatGLM:\n",
    "    \"\"\"\n",
    "    用于处理批量数据的DataCollator，尤其是在使用 ChatGLM 模型时。\n",
    "\n",
    "    该类负责将多个数据样本（tokenized input）合并为一个批量，并在必要时进行填充(padding)。\n",
    "\n",
    "    属性:\n",
    "    pad_token_id (int): 用于填充(padding)的token ID。\n",
    "    max_length (int): 单个批量数据的最大长度限制。\n",
    "    ignore_label_id (int): 在标签中用于填充的ID。\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, pad_token_id: int, max_length: int = 2048, ignore_label_id: int = -100):\n",
    "        \"\"\"\n",
    "        初始化DataCollator。\n",
    "\n",
    "        参数:\n",
    "        pad_token_id (int): 用于填充(padding)的token ID。\n",
    "        max_length (int): 单个批量数据的最大长度限制。\n",
    "        ignore_label_id (int): 在标签中用于填充的ID，默认为-100。\n",
    "        \"\"\"\n",
    "        self.pad_token_id = pad_token_id\n",
    "        self.ignore_label_id = ignore_label_id\n",
    "        self.max_length = max_length\n",
    "\n",
    "    def __call__(self, batch_data: List[Dict[str, List]]) -> Dict[str, torch.Tensor]:\n",
    "        \"\"\"\n",
    "        处理批量数据。\n",
    "\n",
    "        参数:\n",
    "        batch_data (List[Dict[str, List]]): 包含多个样本的字典列表。\n",
    "\n",
    "        返回:\n",
    "        Dict[str, torch.Tensor]: 包含处理后的批量数据的字典。\n",
    "        \"\"\"\n",
    "        # 计算批量中每个样本的长度\n",
    "        len_list = [len(d['input_ids']) for d in batch_data]\n",
    "        batch_max_len = max(len_list)  # 找到最长的样本长度\n",
    "\n",
    "        input_ids, labels = [], []\n",
    "        for len_of_d, d in sorted(zip(len_list, batch_data), key=lambda x: -x[0]):\n",
    "            pad_len = batch_max_len - len_of_d  # 计算需要填充的长度\n",
    "            # 添加填充，并确保数据长度不超过最大长度限制\n",
    "            ids = d['input_ids'] + [self.pad_token_id] * pad_len\n",
    "            label = d['labels'] + [self.ignore_label_id] * pad_len\n",
    "            if batch_max_len > self.max_length:\n",
    "                ids = ids[:self.max_length]\n",
    "                label = label[:self.max_length]\n",
    "            input_ids.append(torch.LongTensor(ids))\n",
    "            labels.append(torch.LongTensor(label))\n",
    "\n",
    "        # 将处理后的数据堆叠成一个tensor\n",
    "        input_ids = torch.stack(input_ids)\n",
    "        labels = torch.stack(labels)\n",
    "\n",
    "        return {'input_ids': input_ids, 'labels': labels, 'attention_mask': (input_ids != self.pad_token_id).long()}\n",
    "\n",
    "\n",
    "        \n",
    "# 准备数据整理器\n",
    "data_collator = DataCollatorForChatGLM(pad_token_id=tokenizer.pad_token_id)\n",
    "\n",
    "\n",
    "\n",
    "_compute_dtype_map = {\n",
    "    'fp32': torch.float32,\n",
    "    'fp16': torch.float16,\n",
    "    'bf16': torch.bfloat16\n",
    "}\n",
    "\n",
    "# QLoRA 量化配置\n",
    "q_config = BitsAndBytesConfig(load_in_4bit=True,\n",
    "                              bnb_4bit_quant_type='nf4',\n",
    "                              bnb_4bit_use_double_quant=True,\n",
    "                              bnb_4bit_compute_dtype=_compute_dtype_map['bf16'],\n",
    "                              llm_int8_enable_fp32_cpu_offload=True  # 关键参数\n",
    "                             )\n",
    "\n",
    "\n",
    "\n",
    "# revision='b098244' 版本对应的 ChatGLM3-6B 设置 use_reentrant=False\n",
    "# 最新版本 use_reentrant 被设置为 True，会增加不必要的显存开销\n",
    "model = AutoModel.from_pretrained(model_name_or_path,\n",
    "                                  quantization_config=q_config,\n",
    "                                  device_map='auto',\n",
    "                                  use_cache=False,  # 训练时关闭（梯度检查点需要重新计算中间结果，而缓存会阻止这一过程）\n",
    "                                  trust_remote_code=True,\n",
    "                                  revision='b098244',\n",
    "                                  max_memory={0: \"7GiB\"}\n",
    "                                 )\n",
    "\n",
    "# 确保使用新版检查点\n",
    "model.gradient_checkpointing_enable()\n",
    "\n",
    "# 获取当前模型占用的 GPU显存（差值为预留给 PyTorch 的显存）\n",
    "memory_footprint_bytes = model.get_memory_footprint()\n",
    "memory_footprint_mib = memory_footprint_bytes / (1024 ** 2)  # 转换为 MiB\n",
    "\n",
    "print(f\"{memory_footprint_mib:.2f}MiB\")\n",
    "\n",
    "kbit_model = prepare_model_for_kbit_training(model)\n",
    "\n",
    "lora_config = LoraConfig(\n",
    "    target_modules=target_modules,\n",
    "    r=lora_rank,\n",
    "    lora_alpha=lora_alpha,\n",
    "    lora_dropout=lora_dropout,\n",
    "    bias='none',\n",
    "    inference_mode=False,\n",
    "    task_type=TaskType.CAUSAL_LM\n",
    ")\n",
    "\n",
    "qlora_model = get_peft_model(kbit_model, lora_config)\n",
    "\n",
    "qlora_model.print_trainable_parameters()\n",
    "\n",
    "# 定义训练参数（演示用，减少训练时间）\n",
    "training_demo_args = TrainingArguments(\n",
    "    output_dir=f\"models/demo/{model_name_or_path}\",  # 输出目录：保存模型和日志的路径\n",
    "    per_device_train_batch_size=16,                 # 每个GPU的训练batch大小：根据显存调整\n",
    "    gradient_accumulation_steps=4,                  # 梯度累积步数：模拟更大的batch size\n",
    "    learning_rate=1e-3,                             # 初始学习率：常用范围1e-5到1e-3\n",
    "    max_steps=100,                                  # 最大训练步数：控制演示时长\n",
    "    lr_scheduler_type=\"linear\",                     # 学习率调度策略：线性衰减\n",
    "    warmup_ratio=0.1,                               # 预热比例：前10%步数用于学习率预热\n",
    "    logging_steps=10,                               # 每10步记录一次日志\n",
    "    save_strategy=\"steps\",                          # 保存策略：按步数保存\n",
    "    save_steps=20,                                  # 每20步保存一次模型\n",
    "    optim=\"adamw_torch\",                            # 优化器：AdamW with torch实现\n",
    "    fp16=True,                                      # 启用混合精度训练：减少显存占用\n",
    "    report_to=[\"tensorboard\"],                      # 添加：记录指标到TensorBoard\n",
    "    gradient_checkpointing_kwargs={\"use_reentrant\": False},  # 显式设置\n",
    ")\n",
    "\n",
    "# 初始化Trainer\n",
    "trainer = Trainer(\n",
    "    model=qlora_model,                              # 要训练的模型（QLoRA适配后的模型）\n",
    "    args=training_demo_args,                        # 训练参数配置\n",
    "    train_dataset=tokenized_dataset,                # 训练数据集（已tokenize）\n",
    "    data_collator=data_collator                    # 数据整理器：处理padding和batch\n",
    ")\n",
    "\n",
    "assert model.config.use_cache is False, \"use_cache未正确关闭!\"\n",
    "# 开始训练并记录损失\n",
    "print(\"开始训练...\")\n",
    "train_result = trainer.train()                      # 返回的训练结果包含指标数据\n",
    "\n",
    "# 保存训练后的模型\n",
    "trainer.model.save_pretrained(f\"models/demo/{model_name_or_path}\")\n",
    "print(\"模型保存完成！\")\n",
    "\n",
    "# --- 新增：绘制训练损失曲线 ---\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.ticker import MaxNLocator\n",
    "\n",
    "# 从训练记录中提取损失值\n",
    "log_history = trainer.state.log_history\n",
    "train_loss = [log['loss'] for log in log_history if 'loss' in log]\n",
    "steps = [log['step'] for log in log_history if 'loss' in log]\n",
    "\n",
    "# 创建图表\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.plot(steps, train_loss, 'b-', linewidth=2, label='Training Loss')\n",
    "plt.title('Training Loss Curve', fontsize=14)\n",
    "plt.xlabel('Training Steps', fontsize=12)\n",
    "plt.ylabel('Loss', fontsize=12)\n",
    "plt.grid(True, linestyle='--', alpha=0.6)\n",
    "plt.gca().xaxis.set_major_locator(MaxNLocator(integer=True))  # X轴只显示整数值\n",
    "\n",
    "# 标记最低损失点\n",
    "min_loss_idx = train_loss.index(min(train_loss))\n",
    "plt.scatter(steps[min_loss_idx], train_loss[min_loss_idx], \n",
    "            c='red', s=100, label=f'Min Loss: {train_loss[min_loss_idx]:.3f}')\n",
    "plt.legend(fontsize=12)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f7dd5dbd-6981-4ee6-9f1a-16789c830b63",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DatasetDict({\n",
      "    train: Dataset({\n",
      "        features: ['content', 'summary'],\n",
      "        num_rows: 114599\n",
      "    })\n",
      "    validation: Dataset({\n",
      "        features: ['content', 'summary'],\n",
      "        num_rows: 1070\n",
      "    })\n",
      "})\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>content</th>\n",
       "      <th>summary</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>类型#裙*材质#绸缎*图案#印花*裙长#连衣裙*裙领型#圆领</td>\n",
       "      <td>小圆领的设计，修饰你的脖颈气质满满。大面积的印花设计提升整体视觉效果，绸缎面的设计亮眼又吸睛，是你值得拥有的一款连衣裙哦。</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>类型#上衣*风格#高贵*风格#性感*图案#蝴蝶结*衣样式#衬衫*衣款式#拼接</td>\n",
       "      <td>双色拼接而出的典雅时尚，对比强烈的网格花纹，吸睛夺目，演绎别致性感魅力。立体的衬衫领，结合俏皮的蝴蝶结萦绕&lt;UNK&gt;，优雅又不失甜美气质。斜边扣开叉裙摆，时尚大气展露美腿魅惑，经典的x字版型，勾勒出凹凸有致的曼妙身姿，让你举手&lt;UNK&gt;间尽显高贵名媛气质。</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>类型#上衣*版型#显瘦*材质#羊绒*颜色#紫色*风格#复古*图案#复古*衣样式#开衫*衣门襟#一粒扣*衣款式#亮片</td>\n",
       "      <td>整身&lt;UNK&gt;饱和的粉紫色为基调，会让人联想到浪漫的薰衣草，外搭的开衫，简单的在门襟点缀一粒扣，渲染出复古风情，背心连身裙，融入亮片装饰，多了一些前卫和时髦的视觉效果。包臀的版型和抹胸的领口，展示十足女性魅力，与上身开衫结合在一起，能修饰女性身形，显高显瘦，打造出明亮摩登的视觉效果。羊绒面料制作，让质感提升。</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>input_ids</th>\n",
       "      <th>labels</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[64790, 64792, 30910, 33467, 31010, 49534, 30998, 37505, 31010, 41260, 30998, 37505, 31010, 32502, 30998, 37505, 31010, 45859, 30998, 55500, 46025, 31010, 55233, 55500, 30998, 55500, 54847, 54888, 31010, 55740, 54847, 30910, 34372, 54835, 45578, 41260, 45859, 42128, 54534, 55233, 55500, 54530, 56896, 54815, 54542, 54578, 56164, 54807, 31123, 41398, 55846, 39298, 42128, 31827, 31123, 32428, 54541, 32425, 51130, 37539, 33286, 33870, 54706, 31155, 55740, 54847, 34481, 40697, 33894, 31123, 51605, 54657, 55101, 33550, 37003, 54530, 54888, 55033, 35642, 31155, 2]</td>\n",
       "      <td>[-100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, 30910, 34372, 54835, 45578, 41260, 45859, 42128, 54534, 55233, 55500, 54530, 56896, 54815, 54542, 54578, 56164, 54807, 31123, 41398, 55846, 39298, 42128, 31827, 31123, 32428, 54541, 32425, 51130, 37539, 33286, 33870, 54706, 31155, 55740, 54847, 34481, 40697, 33894, 31123, 51605, 54657, 55101, 33550, 37003, 54530, 54888, 55033, 35642, 31155, 2]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f325ff7adfaf4658bd4f2a35f99719fe",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "You are using an old version of the checkpointing format that is deprecated (We will also silently ignore `gradient_checkpointing_kwargs` in case you passed it).Please update to the new format on your modeling file. To use the new format, you need to completely remove the definition of the method `_set_gradient_checkpointing` in your model.\n",
      "You are using an old version of the checkpointing format that is deprecated (We will also silently ignore `gradient_checkpointing_kwargs` in case you passed it).Please update to the new format on your modeling file. To use the new format, you need to completely remove the definition of the method `_set_gradient_checkpointing` in your model.\n",
      "No label_names provided for model class `PeftModelForCausalLM`. Since `PeftModel` hides base models input arguments, if label_names is not given, label_names can't be set automatically within `Trainer`. Note that empty label_names list will be used instead.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当前模型占用显存（单位为MiB）： 3739.6914672851562\n",
      "3739.69MiB\n",
      "trainable params: 974,848 || all params: 6,244,558,848 || trainable%: 0.0156\n",
      "开始训练...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      \n",
       "      <progress value='100' max='100' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      [100/100 47:57, Epoch 0/1]\n",
       "    </div>\n",
       "    <table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       " <tr style=\"text-align: left;\">\n",
       "      <th>Step</th>\n",
       "      <th>Training Loss</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>10</td>\n",
       "      <td>4.667800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>20</td>\n",
       "      <td>3.793500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>30</td>\n",
       "      <td>3.607000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>40</td>\n",
       "      <td>3.509600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>50</td>\n",
       "      <td>3.447400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>60</td>\n",
       "      <td>3.413400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>70</td>\n",
       "      <td>3.371300</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>80</td>\n",
       "      <td>3.379500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>90</td>\n",
       "      <td>3.377200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>100</td>\n",
       "      <td>3.366300</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table><p>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n",
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n",
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n",
      "/usr/local/lib/python3.10/dist-packages/torch/_dynamo/eval_frame.py:838: UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.\n",
      "  return fn(*args, **kwargs)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型保存完成！\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1IAAAIoCAYAAABj6NoUAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjUsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvWftoOwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAq8tJREFUeJzs3Xd8FHX6B/DP7KZCGqElQCgJSAQSELAgICBNDzkL6k9AKZa7U892eip3omA5QNTT886GBeyFo5yoFIGoKJwgojFAKAETCSGShBRI3ZnfH3O7yabvk83OzObzfr32xWZ2dvf7/cwm5MnMPKNomqaBiIiIiIiIms1m9ACIiIiIiIishoUUERERERGRh1hIEREREREReYiFFBERERERkYdYSBEREREREXmIhRQREREREZGHWEgRERERERF5iIUUERERERGRh1hIEREREREReYiFFBERuSiKgrFjx7boNVJSUqAoChYsWOCVMREREZkRCykiIpNRFMWjGzWtd+/eCAkJMXoYXnHs2DHMmzcPQ4cORVRUFIKCghAbG4spU6Zg+fLlqKioMHqIRERtQoDRAyAiInePPPJInWXPPvssCgsL633Mm/bt24d27dq16DXOO+887Nu3D506dfLSqMjpvffew0033YTS0lIMGzYM119/PSIjI5GTk4MtW7Zg7ty5eOutt7B582ajh0pE5PcUTdM0owdBRESN6927N37++WfwR7ZM7969kZOTg7KyMqOHIrZ+/XpMmTIFUVFReP/99zFx4kS3xzVNw5o1a/Dqq6/ik08+MWiURERtBw/tIyKyqKNHj0JRFMyZMwf79u3DlVdeiY4dO0JRFBw9ehQAsHr1akyfPh19+/ZFu3btEBkZidGjR+Pf//53va9Z3zlSc+bMgaIoOHLkCP7xj38gMTERwcHB6NWrFxYuXAhVVd3Wb+gcqd69e6N3794oKSnBXXfdhW7duiE4OBjJyclYuXJlg3P8v//7P0RHRyMsLAxjxozBl19+iQULFkBRFKSkpEiia9Tp06fxyCOPIDExESEhIYiOjsaUKVPw9ddf11m3rKwMTz/9NAYPHozIyEi0b98evXv3xrXXXosffvjBtZ6qqnj11Vdx3nnnITo6GqGhoejRowemTp3arDk4HA7cfvvtUFUVH374YZ0iCtC33ZVXXolVq1a5ljWW0/Lly6EoCpYvX+5a1thnau/evQgPD0dCQkKD40xOTkZoaCiKiopcyzRNw+uvv46RI0ciIiIC7dq1w/Dhw/H66683OW8iIjPjoX1ERBZ36NAhXHDBBUhKSsKcOXOQl5eHoKAgAMC8efMQFBSEUaNGITY2Fr/++iv+85//4Oqrr8Y//vEP3HHHHc1+nz//+c/44osvcNlll2Hy5MlYs2YNFixYgIqKCjzxxBPNeo3KykpMmjQJBQUFmDZtGs6cOYP3338f1157LdavX49Jkya51j127BguvPBCHD9+HJdccgnOOeccpKenY+LEibj44os9C6mZysrKcPHFF+Pbb7/F0KFDcffdd+PEiRP44IMPsGHDBrz33nu45pprXOvPnj0bH374IZKTkzF37lwEBwcjKysLW7duxc6dOzF48GAA+nZ48sknkZCQgBkzZiA8PBzHjh3Dtm3b8PnnnzfZ4GPr1q3IyMjAhRdeiPHjxze6bnBwcItzqO8zFRUVhWnTpmHFihX45ptvcOGFF7o954cffkBqair+7//+DxEREQD0ImrmzJl477330K9fP8yYMQNBQUHYtGkTbrrpJuzduxdPPfVUi8dLRGQIjYiITK9Xr15a7R/ZR44c0QBoALSHH3643ucdPny4zrLi4mItKSlJi4yM1E6fPu32GABtzJgxbstmz56tAdD69OmjZWdnu5b/+uuvWlRUlBYeHq6Vl5e7lm/dulUDoD3yyCP1zuHyyy93W//zzz/XAGiTJ092W//666/XAGhPPPGE2/LXXnvNNe+tW7fWO+/aevXqpQUHBze53sKFCzUA2syZMzVVVV3Ld+/erQUFBWlRUVFaUVGRpmmadurUKU1RFG3YsGFaVVWV2+tUVVVpBQUFrq+jo6O1bt261clb0zQtLy+vyXEtWLBAA6A99NBDTa5b0yOPPNJgTm+88YYGQHvjjTdcy5r6TDm31a233lrnsXvvvVcDoK1bt8617JVXXtEAaHPnztUqKipcy8vLy7WpU6dqALRdu3Z5NCciIrPgoX1ERBYXExODv/71r/U+Fh8fX2dZWFgY5syZg8LCQuzcubPZ7zN//nzExsa6vu7UqRMuv/xyFBcXIz09vdmv8/e//921xwwAxo8fj169ermNpby8HB999BG6dOmCe++91+35c+fORf/+/Zv9fp5YsWIFAgMDsXjxYreOiOeccw5mz56NU6dOYc2aNQD0Q+k0TUNISAhsNvf/Tu12O6KiotyWBQUFwW6313nP6OjoJseVk5MDAOjRo4eHM5Jp6DM1btw4dO/eHR9++CEqKytdy1VVxbvvvovOnTtj8uTJruX//Oc/0b59e/zrX/9CYGCga3lQUJBrL+Z7773XijMhImo9PLSPiMjiBg8e7FaY1JSbm4vFixfjs88+w88//4zS0lK3x7Ozs5v9PsOGDauzzPmL/alTp5r1GlFRUejTp0+9r7N9+3bX1+np6SgvL8fw4cPrHKqmKAouvPBCj4q35igqKkJGRgbOPvvseguWcePGYdmyZdizZw9uuOEGRERE4De/+Q0+/fRTDB06FNdccw3Gjh2Lc889161oAIDrrrsOL7zwAgYNGoTrrrsO48aNw4gRIxAaGurVOXhLQ58pm82GmTNn4sknn8Snn36Kyy+/HACwefNmHD9+HHfccQcCAvRfLc6cOYPU1FR069YNS5YsqfNazkJs//79rTgTIqLWw0KKiMjiunbtWu/y/Px8nHvuucjMzMTIkSMxYcIEREVFwW63Y8+ePVi7di3Ky8ub/T7O815qcv7S7HA4mvUakZGR9S4PCAhwa1rhbFbQpUuXetdvaM4t4XzPhl7buTeuZiOFjz76CH/729/w7rvvuvbgREREYO7cufjb3/7maiX/3HPPoU+fPnjjjTfw+OOP4/HHH0dISAiuvfZaPP300022io+JiQGgnzfmC43le8MNN+DJJ5/E22+/7Sqk3nrrLddjTgUFBdA0DceOHcPChQsbfL3Tp097adRERL7FQ/uIiCyuoYvyvvbaa8jMzMRjjz2Gbdu24fnnn8djjz2GBQsW4IILLvDxKD3jLNpyc3PrffzEiROt9p4Nvbbz8LqaBWW7du3w+OOPIyMjAxkZGXjttdfQv39/PPfcc7jnnntc6wUEBOC+++5DWloajh07hnfffRejR4/Gm2++iZkzZzY5tpEjRwKAx9eHch5yWFVVVeexwsLCBp/X2IWeBw0ahCFDhmDdunUoLCzEmTNnsHr1avTv3x/nnnuuaz1nTsOGDYOmaQ3etm7d6tGciIjMgoUUEZGfOnz4MAC49hrU9NVXX/l6OB7p378/goOD8d1339XZa6ZpmtthgN4SERGB+Ph4HDp0qN49P84W4kOGDKn3+X369MGNN96IL774AmFhYfjPf/5T73rdunXD9OnTsX79evTt2xeff/55nUMuaxs3bhzi4+PxzTffNFl41MyrQ4cOAOrfk/X99983+jqNueGGG1BWVoaVK1di9erVKCkpwfXXX++2Tnh4OM4++2zs27ev2Yd+EhFZCQspIiI/1atXLwDAtm3b3Ja/++67+PTTT40YUrMFBwfj6quvxokTJ/Dss8+6Pfbmm2+22nk1s2fPRmVlJebNm+d28eMff/wRy5cvR2RkJK644goAwK+//oqffvqpzmsUFBSgvLwcISEhAPTC5ptvvqmz3unTp1FSUoLAwMA6zSpqs9vt+Ne//gWbzYZrr70WW7ZsqXe9jz/+GFdffbXra+ceojfffNPt0Mnt27fjnXfeafQ9GzNjxgzY7Xa89dZbeOutt6AoSp1CCgDuvPNOnDlzBrfccku9h/AdOXLEdc0zIiKr4TlSRER+6oYbbsCSJUtwxx13YOvWrejVqxd++OEHbN68GVdddZXbhVvNaNGiRfj888/x4IMP4osvvnBdR2rdunW45JJLsH79+iYLkJoqKysxZ86cBh9fvnw57r//fnzyySd46623sG/fPowfPx65ubn44IMPUFVVhWXLliE8PByAvpfnnHPOweDBg5GcnIzu3bsjLy8Pa9euRWVlJe677z4AQGlpKUaOHImzzjoLw4YNQ8+ePVFSUoJ169YhJycH9913X7Ou/XTJJZfgrbfews0334zx48dj+PDhGDFiBMLDw3HixAmkpKTg8OHDmDBhgus5F1xwAUaOHIktW7ZgxIgRuOiii/Dzzz9j7dq1mDp1KlavXt3s/GqKiYnBhAkTsHHjRthsNowaNQq9e/eus97vf/977NixAytWrMDXX3+NCRMmoFu3bjhx4gT279+P//73v3j33XfrfS4RkdmxkCIi8lM9evTAF198gfvvvx+ff/45qqqqMHToUGzcuBFZWVmmL6Ti4uKwfft2PPDAA9i4cSO++OILDBs2DBs3bsRHH30EoP4GGA1RVRUrVqxo8PHly5cjJCQEW7ZswZIlS/DBBx/g73//O9q1a4cxY8bgL3/5C0aNGuVav3fv3liwYAG2bNmCzz//HHl5eejUqROGDh2Ku+66C5dccgkAoH379liyZAk2b96Mr776Crm5uejQoQP69++PRYsW4brrrmv2HGbMmIExY8bg+eefx8aNG7FixQqcOXMGHTt2xDnnnIOHHnqozjlXa9euxZ/+9CesW7cOqampGDx4MD7++GNkZ2eLCylAL9Q3bNgAh8NR794oQD/Xavny5fjNb36DZcuWYd26dSgpKUGXLl3Qr18/PPXUU26FHxGRlShazWMXiIiILGDUqFHYvn07CgsLERYWZvRwiIioDeI5UkREZFrHjx+vs+ztt992HSbGIoqIiIzCPVJERGRazkPWBgwY4Lr+VUpKCsLDw/H1118jKSnJ6CESEVEbxUKKiIhM669//Ss+/vhjZGZm4vTp0+jcuTPGjRuH+fPnIzEx0ejhERFRG8ZCioiIiIiIyEM8R4qIiIiIiMhDLKSIiIiIiIg81OavI6WqKrKzsxEeHg5FUYweDhERERERGUTTNBQXF6Nbt25NXvS9zRdS2dnZiIuLM3oYRERERERkEllZWejRo0ej67T5Qio8PByAHlZERITBowEcDgfS0tIwcOBA2O12o4djGcxNhrnJMDc5ZifD3GSYmwxzk2N2MmbKraioCHFxca4aoTFtvpByHs4XERFhmkIqLCwMERERhn+QrIS5yTA3GeYmx+xkmJsMc5NhbnLMTsaMuTXnlJ823/68qKgIkZGRKCwsNEUhpWkaysrKEBISwnO2PMDcZJibDHOTY3YyzE2GuckwNzlmJ2Om3DypDdi1z4SCgoKMHoIlMTcZ5ibD3OSYnQxzk2FuMsxNjtnJWDE3FlImo6oqUlNToaqq0UOxFOYmw9xkmJscs5NhbjLMTYa5yTE7GavmxkKKiIiIiIjIQ22+2QQRERFRW+dwOFBZWem67zxnxSwn/lsFs5PxVW6BgYFefX0WUkRERERtlKZpyMnJwalTp9yW2Ww2/Pzzz4af+G81zE7Gl7lFRUUhJibGK+/Drn0m7NqnqipsNhu/AT3A3GSYmwxzk2N2MsxNhrk17fjx4zh16hS6dOmCdu3aQVEU1PzVkLl5htnJ+CI3TdNw5swZ5ObmIioqCrGxsfWu50ltwD1SJlRRUYGQkBCjh2E5zE2GuckwNzlmJ8PcZJhbwxwOh6uI6tixo2u5pmnQNA2KorAY8BCzk/FVbqGhoQCA3NxcdOnSpcWH+bHZhMmoqor09HTLdS0xGnOTYW4yzE2O2ckwNxnm1jjnOVHt2rWr81hZWZmvh+M3mJ2Mr3Jzft6dn/+WYCFFRERE1IZxzwm1Jd78vLOQIiIiIiIi8hALKRNiu0wZ5ibD3GSYmxyzk2FuMsyNiFoLCymTsdvtSEpK4g9+DzE3GeYmw9zkmJ0Mc5NhbjKKorg6+FHD5syZg969e7sta252CxYsYL41WPUzx0LKZDRNQ1FREdp4V3qPMTcZ5ibD3OSYnQxzk2FuMpqmuS6QakXOzm9N3VJSUrz+3lbIbs6cOQgLCzN6GG6skFt92P7cZFRVRUZGBv+C5iHmJsPcZJibHLOTYW4yzE2uvLzc1Sraat566y23r998801s2rSpzvKzzz67Re+zbNmyejtCNie7hx56CA8++GCL3t/fWPEzx0KKiIiIiPzG9ddf7/b1jh07sGnTpjrLaztz5ky9reAbEhgYKBofAAQEBCAggL+GWx0P7TOJ4mLgmWeASy+1YfHi7kYPh4iIiMhvjR07FoMGDcJ3332Hiy66CO3atcNf/vIXAMDatWsxZcoUdOvWDcHBwUhISMBjjz0Gh8Ph9hq1z5E6evQobDYbnn32WbzyyitISEhAcHAwzj33XOzcudPtufWdI6UoCv74xz9izZo1GDRoEIKDgzFw4ECsX7++zvhTUlIwfPhwhISEICEhAS+//LLXz7v66KOPMGzYMISGhqJTp064/vrrcezYMbd1cnJyMHfuXPTo0QPBwcGIjY3F5ZdfjqNHj7rW2bVrFyZPnoxOnTohNDQUffr0wY033ui1cRqJpbBJBAQAf/0rUFamICYmChY7RNQUeOV6GeYmw9zkmJ0Mc5NhbjJWO+lfIi8vD5deeimuu+46XH/99ejatSsAYPny5QgLC8Of/vQnhIWFYcuWLXj44YdRVFSEpUuXNvm6H374IU6fPo3f//73UBQFTz75JK666ipkZGQ0uRdr27ZtWLVqFW677TaEh4fjH//4B6ZNm4bMzEx07NgRAPD999/jkksuQWxsLBYuXAiHw4FHH30UnTt3bnko/7N8+XLMnTsX5557LhYtWoQTJ07gueeew9dff43vv/8eUVFRAIBp06YhLS0Nd9xxB3r37o3c3Fxs2rQJmZmZrq8nTZqEzp0748EHH0RUVBSOHj2KVatW1XlPS37mtDausLBQA6AVFhYaPRRt0iRNA/RbWprRoyEiIiJ/Vlpaqu3du1crLS01eiit6vbbb9dq/8o7ZswYDYD20ksv1Vn/zJkzdZb9/ve/19q1a6eVlZW5ls2ePVvr1auX6+sjR45oALSOHTtq+fn5ruVr167VAGgff/yxa9kjjzxSZ0wAtKCgIO3QoUOuZT/88IMGQHv++eddy6ZOnaq1a9dOO3bsmGvZwYMHtYCAgDqvWZ/Zs2dr7du3b/DxiooKrUuXLtqgQYPcPhvr1q3TAGgPP/ywpmmaVlBQoAHQli5d2uBrrV69WgOg7dy5s8lx+UpTn3tPagMe2mcikydX31+/vu7Ji9QwVVWRl5dX70mf1DDmJsPc5JidDHOTYW4ymqZh2DANPXpo6NEDht+GD2+deQYHB2Pu3Ll1ltdseFBcXIyTJ09i9OjROHPmDPbv39/k615zzTWuPTYAMHr0aABARkZGk8+dMGECEhISXF8nJycjIiLC9VyHw4HPP/8cV1xxBbp16+Zar2/fvrj00kubfP3m2LVrF3Jzc3Hbbbe57dGdMmUKEhMT8cknnwDQcwoKCkJKSgoKCgrqfS1nDuvWrUNlZWWD76lpGqqqqti1j+QmTwbuvVe/v2GDgj/9ydjxWImmacjKynL7wUVNY24yzE2O2ckwNxnmJpeToyE727//3t69e3cEBQXVWZ6WloaHHnoIW7ZsQVFRkdtjhYWFTb5uzQIHADp06AAADRYbNfXs2bPOsg4dOriem5ubi9LSUvTt27fOevUtk/j5558BAP3796/zWGJiIrZt2wZAL0SXLFmCe++9F127dsUFF1yAyy67DLNmzUJMTAwAYMyYMZg2bRoWLlyIv//97xg7diyuuOIKzJgxA8HBwW6vXVFRwa59JDdgANC9u4ZjxxR8+SVQWgpY7PNEREREfqBrVw2KogEw/ryV//1O7nX1/dJ+6tQpjBkzBhEREXj00UeRkJCAkJAQ7N69Gw888ECz9m421Gq/OXtbWvJcI9x9992YOnUq1qxZgw0bNmD+/PlYtGgRtmzZgnPOOQeKomDlypXYsWMHPv74Y2zYsAE33ngjnn76aezYscN017PyFAspE1EUYNIkDW+8oaCsTMFXXwGTJhk9KiIiImprtm3Tr+ljxfP/WyIlJQV5eXlYtWoVLrroItfyI0eOGDiqal26dEFISAgOHTpU57H6lkn06tULAJCeno6LL77Y7bH09HTX404JCQm49957ce+99+LgwYMYMmQInn76abz99tuudS644AJccMEFeOKJJ/Duu+9i5syZeP/993HzzTd7ZcxG8e99thZUs3DasMG4cVhReHi40UOwJOYmw9zkmJ0Mc5NhbjI2W9v8FdG5R6jmHqCKigq88MILzX6N1uw+Z7fbMWHCBKxZswbZ2dmu5YcOHcJnn33mlfcYPnw4unTpgpdeegnl5eWu5Z999hn27duHKVOmANCvu1VWVub23ISEBISHh7ueV1BQUGdv2pAhQwDA7bUBa37muEfKZCZNssFmA1RVL6SeftroEVmD3W53OzmTmoe5yTA3OWYnw9xkmJuMoihttm38hRdeiA4dOmD27Nm48847oSgK3nrrLY8OrQsMDGzVYmrBggXYuHEjRo4ciVtvvRUOhwP//Oc/MWjQIOzZs6dZr1FZWYnHH3+8zvLo6GjcdtttWLJkCebOnYsxY8Zg+vTprvbnvXv3xj333AMAOHDgAMaPH49rr70WAwYMQEBAAFavXo0TJ07guuuuAwCsWLECL7zwAq688kokJCSguLgYy5YtQ0REBH7zm9+43teqnzkWUiYTFaViyJAq7N4dhLQ04Jdf9I411DhVVZGbm4suXbpY8i8aRmFuMsxNjtnJMDcZ5ibj7KAWEBBgzWv7tEDHjh2xbt063HvvvXjooYfQoUMHXH/99Rg/fjwm12yv3AiHwwFN01otu2HDhuGzzz7Dfffdh/nz5yMuLg6PPvoo9u3b16yugoC+l23+/Pl1lickJOC2227DnDlz0K5dOyxevBgPPPAA2rdvjyuvvBJLlixxNW+Ji4vD9OnTsXnzZrz11lsICAhAYmIiPvzwQ0ybNg2A3mzi22+/xfvvv48TJ04gMjIS5513Ht555x306dPH9b5W/cwpmlnPXvORoqIiREZGorCwEBEREUYPBw6HA7fd9iteeUU/s/K11wA/ufhzq3I4HEhNTUVSUlKDJ2pSXcxNhrnJMTsZ5ibD3BpXVlaGI0eOoE+fPm57AzRNQ2lp6f/OkbLOL7VmYGR2V1xxBdLS0nDw4EGfvq83+DK3hj73Tp7UBvzzjAmNGFHdapPnSRERERFRTaWlpW5fHzx4EJ9++inGjh1rzIDaKB7aZ0KDBp1BZKSGwkIFmzYBDgfAP6QREREREQDEx8djzpw5iI+Px88//4wXX3wRQUFBuP/++40eWpvCQspkFEVBly7RGD8eWLUKKCgAdu0Czj/f6JGZm6IoiI6O5iEIHmJuMsxNjtnJMDcZ5ibHQyHlfJHdJZdcgvfeew85OTkIDg7GiBEj8Le//Q39+vVr9fduLVb8zLGQMhmbzYaePXvikkv0QgrQD+9jIdU4Z27kGeYmw9zkmJ0Mc5NhbjKKoiA4ONjoYViSr7J74403Wv09fMmqnzmeI2UyqqoiMzMTEydWXzmb50k1zZlbc644TtWYmwxzk2N2MsxNhrnJaJqG8vJyj1p+k47ZyVg1NxZSJqNpGvLz8xEXpyExUV/23/8Cp04ZOizTc+ZmtW9AozE3GeYmx+xkmJsMc5NzOBxGD8GymJ2MFXNjIWVizssVOBzA5s3GjoWIiIiIiKqxkDKxmtd94+F9RERERETmwULKZBRFQUxMDBRFwZgxgPO8uw0bAB6Z0LCauVHzMTcZ5ibH7GSYmwxzkwsMDDR6CJbF7GSsmJtpC6nFixdDURTcfffdja536tQp3H777YiNjUVwcDDOOussfPrpp74ZZCuw2WyIiYmBzWZDu3bARRfpyzMzgfR0Y8dmZjVzo+ZjbjLMTY7ZyTA3GeYmoygKAgMDWYAKMDsZq+Zmyp8sO3fuxMsvv4zk5ORG16uoqMDEiRNx9OhRrFy5Eunp6Vi2bBm6d+/uo5F6n8PhwOHDh10n3PHwvuapnRs1D3OTYW5yzE6GuckwNxlN01BWVsYmHQLMTsaquZmukCopKcHMmTOxbNkydOjQodF1X3/9deTn52PNmjUYOXIkevfujTFjxmDw4ME+Gm3rKC4udt1nIdV8NXOj5mNuMsxNjtnJMDcZ5ibDlvFyzE7GirmZ7oK8t99+O6ZMmYIJEybg8ccfb3Td//znPxgxYgRuv/12rF27Fp07d8aMGTPwwAMPNHh15PLycpSXl7u+LioqAqD/1cr5FytFUWCz2aCqqltl7Fxe+y9bDS232WxQFKXe5UDdD4zNZoOmadA0zfWcxESge3c7jh0DUlI0nD6tIiREX99ut9cZY0PLjZxTfcvtdjs0Tat3uWRODofDlZu/zMkX28mZm/PmD3Nqark35uR8bu3XsPKcfLWdan6v+sucfLGdnLmpqtroXK00p9pjbI051fwZ19y5mn1OjY3d0zkBcPs/oL7Hao+zvvW8tdwTrTkWm82GRx55BI888ojHr+N8TDK/1s7XzNupofvSMTZnOzl/96/vd6PmMlUh9f7772P37t3YuXNns9bPyMjAli1bMHPmTHz66ac4dOgQbrvtNlRWVtb74QeARYsWYeHChXWWp6WlISwsDAAQHR2Nnj174pdffkF+fr5rnZiYGMTExODo0aNuf+GKi4tDx44dcfDgQZSVlbmWx8fHIyIiAnv37nXbKP3790dQUBBSU1PdxpCUlITy8nLk5+cjLS0NiqLAbrdj0qQkvPEGUFqq4K23juCCC0oQEhKCxMREFBQUICsry/Ua4eHhSEhIQG5uLnJyclzLjZxTRUUF0muc4GW325GUlITi4mJkZGS4lrdkTnl5ea7cYmNj/WJOvthOzmusqKqKyspKv5iTL7aTc295dnY2CgoK/GJOvtpOaWlpbj/j/GFOvthOzu/V7Oxs9OrVyy/m5Ivt5PxlSVVV7N271y/mBHhvO/Xu3RuqqrodUmWz2RAcHOxaXvN1goODUVFR4TaWwMBABAYGory8vLpQ0zQEFRcjoKwMZXY7tOho4H/nvgQHB8Nut6O0tNRt7CEhIVAUpc7y0NBQ12FfNbVr1w6qqrr9cVxRFISGhsLhcOC1117DH/7wBwDA559/jvHjx6OqqgqVlZX/G6KG/v3749ixY7j00kuxcuVK1OY2JwBBQUEICAiocwha7TlVVVWhrKzMNacbbrgBa9asQW5ubovmVFFR4Vpus9kQEhLiNiePt1Mz53T//fdj27ZtyMzMRFlZGXr16oWrrroKd911l+t354bmpCgKbr/9duzYsQPHjh2Dw+FAfHw8brrpJvzud79ze0/neDds2IBFixZhz549UFUV/fr1wwMPPIArrrjCbU5lZWVYvHgxPvzwQxw/fhwdO3bE+eefjxUrViAiIqLBOZWVlaGyshIHDhyAoih1vp9KSkpqfxQapGgmORgxKysLw4cPx6ZNm1znRo0dOxZDhgzBs88+W+9zzjrrLJSVleHIkSOuPVDPPPMMli5diuPHj9f7nPr2SMXFxSE/Px8REREAjP1LkqqqyM/PR1RUlGu9lSvtuO46fZ0//UnFk0/qY/LHv461ZI/UqVOnEBUVBbvd7hdz8sV2UlUVp06dQnR0tOt9rT6nppZ7Y06apqGwsBCRkZFuJ8ZaeU6+2k5VVVWu71WbzeYXc/LFdnJ+r3bo0AEBAQF+MafaY2yNOamqisLCwnpPFbDqnBobu6dzqqysREZGBvr06YMQ5+Eu/1NVVQW73V7nZ1yjf/0/dQpYsQL45z+hHD7selxLSAD++Edg9mwgKsonezqWL1+OG2+8ESEhIZgzZw5efPFFt/VTUlJw8cUXIzg4GBMmTMDHH3/seqysrAyBgYH1Ht3U3D0dNbObO3cuVq5c2eRhpmbb8+RcPnr0aAwdOhR9+/ZFSEgIvv/+e7zxxhsYPnw4vvjiC9fnrj4FBQX4zW9+g9GjR6N3796w2WzYvn073n77bVx33XV45513AFT/0eOtt97CzTffjIkTJ2Lq1Kmw2+1IT09Hjx49cO+997pet7CwEGPHjsUvv/yCW265BX379sWvv/6Kbdu24c0330R0dHSDcyotLcWRI0fQq1cvhISE1Pm+KSoqQnR0NAoLC121QYM0k1i9erUGQLPb7a4bAE1RFM1ut2tVVVV1nnPRRRdp48ePd1v26aefagC08vLyZr1vYWGhBkArLCz0yjxaw8mTmqYomgZoWlKS0aMhIiIif1BaWqrt3btXKy0tbfmLrV+vae3b67+wOH9pcd6cy9q319fzgTfeeEMDoF111VVap06dtMrKSrfHb7nlFm3YsGFar169tClTprTqWGbPnq21b9++Vd/D15566ikNgLZ9+3bR8//4xz9qALTjx4+7lh05ckQLDQ3V7rzzziaff+utt2pRUVFaRkaGx+/d1Ofek9rANM0mxo8fj9TUVOzZs8d1Gz58OGbOnIk9e/bU+1eBkSNH4tChQ25/YTlw4ABiY2MRFBTky+F7jcPhwP79+93++tSxI3Duufr91FTg2DGDBmdi9eVGTWNuMsxNjtnJMDcZ5iajaRpKS0ubv9dowwZgyhSgtLS6fHJ/Qf1WWqqv58PuWdOnT0deXh42bdrkWlZRUYGVK1dixowZ9T5HURQsWLDA9fWCBQugKAoOHTqEOXPmICoqCpGRkZg7dy7OnDnj9lyPs6vho48+wrBhwxAaGopOnTrh+uuvx7Fav/Tl5ORg7ty56NGjB4KDgxEbG4vLL78cR48eda2za9cuTJ48GZ06dUJoaCj69OmDG2+80e11jh8/jv3797sdFuiJ3r17A9AvQ+SN52uahn/+859wOBx49NFHAeiH2NWX46lTp/DGG2/gd7/7Hfr06YOKigq3o818yTSFVHh4OAYNGuR2a9++PTp27IhBgwYBAGbNmoV58+a5nnPrrbciPz8fd911Fw4cOIBPPvkEf/vb33D77bcbNQ2vqH18KeDevW/jRh8OxkLqy42axtxkmJscs5NhbjLMTabZhcCpU8C0aXqhVE8zCzeqqq83bZr+PB/o3bs3RowYgffee8+17LPPPkNhYSGuc5430UzXXnstiouLsWjRIlx77bVYvnx5vefdS4qo5cuX49prr4XdbseiRYtwyy23YNWqVRg1apRbsTJt2jSsXr0ac+fOxQsvvIA777wTxcXFyMzMBADk5uZi0qRJOHr0KB588EE8//zzmDlzJnbs2OH2fvPmzcPZZ59dp1BrSFVVFU6ePIns7Gxs3LgRDz30EMLDw3Heeec16/kVFRU4efIksrKysHr1ajz11FPo1asX+vbt61pny5YtSExMxKeffooePXogPDwcHTt2xPz58912mmzbtg1lZWXo27cvrr76arRr1w6hoaEYOXIk9uzZ06zxeIupmk00JTMz0+04zLi4OGzYsAH33HMPkpOT0b17d9x111144IEHDBxl65g8GXjsMf3+hg3A3LnGjoeIiIgIK1YAZ87U3QvVEFXV13/zTeDOO1t3bP8zY8YMzJs3D6WlpQgNDcU777yDMWPGoFu3bh69zjnnnIPXXnvN9XVeXh5ee+01LFmypEXjq6ysxAMPPIBBgwbhyy+/dJ2vNmrUKFx22WX4+9//joULF+LUqVP45ptvsHTpUtx3332u59fcyfDNN9+goKAAGzduxPDhw13Lm+qE3ZRdu3ZhxIgRrq/79++P//znP4iOjm7W81etWoXp06e7vh4+fDhef/11BARUlyKHDx+G3W7H3Llzcf/992Pw4MFYtWoVHn/8cVRVVWHRokUAgIMHDwLQ552QkIA333wThYWFWLhwIS6++GJX4zFfMM0eqfqkpKS4NZpISUnB8uXL3dYZMWIEduzYgbKyMhw+fBh/+ctfGmx9bmXnnw9ERur3N20CeJQCERERGUrTgOeflz33H/9ofvHVQtdeey1KS0uxbt06FBcXY926dQ0e1tcYZxdAp9GjRyMvL891KR2pXbt2ITc3F7fddptb048pU6YgMTERn3zyCQC9M15QUBBSUlLcOsbWFBUVBQBYt25do4ftLV++HJqmuQ6xa8qAAQOwadMmrFmzBvfffz/at2/vUXe7cePGYdOmTfjoo4/whz/8AYGBgTh9+rTbOiUlJSgoKMDChQvx6KOPYtq0aXjnnXdwySWX4LnnnnM163C+r6Io2Lx5M2bMmIFbb70Va9asQUFBAf71r381e1wtZepCqi2y2WyIj4+v0wElIAAYP16/n58PfPedAYMzsYZyo8YxNxnmJsfsZJibDHOTCw4ObnqlvDzg8GHPCyJN059XozV8a+rcuTMmTJiAd999F6tWrYLD4cDVV1/t8ev07NnT7WtnN8jaRU2zsqvh559/BqDv5aktMTHR9XhwcDCWLFmCzz77DF27dsVFF12EJ5980q31/pgxYzBt2jQsXLgQnTp1wuWXX4433nijxecQRUREYMKECbj88suxZMkS3Hvvvbj88svxww8/NOv5Xbt2xYQJE3D11VfjxRdfxGWXXYaJEye6jT00NBQA3PZcOb8uLS3F999/77be1KlTXe3XAeCCCy5Anz598M0337Rorp7gTxaTURQFERERbu1GnWqeJ+XD8zQtobHcqGHMTYa5yTE7GeYmw9xknNexbDI3D/ZI1KuJduDeNGPGDHz22Wd46aWXcOmll7r23HiioSOeap4T1ezshO6++24cOHAAixYtQkhICObPn4+zzz7bVWQoioKVK1di+/bt+OMf/4hjx47hxhtvxLBhwzzag9SUq666CoB+DViJq6++GiUlJVi7dq1r3M5DLbt27eq2bpcuXQBUF6wNredct6G9da2BhZTJOBwOpKam1tthiIVUwxrLjRrG3GSYmxyzk2FuMsxNRtM0nDlzpummCTX2BoiEh7fs+R648sorYbPZsGPHDtFhfc3V7Oxq6NWrFwC4XUjZKT093fW4U0JCAu69915s3LgRP/30EyoqKvD000+7rXPBBRfgiSeewK5du/DOO+8gLS1NXPTUx3lh38LCQtHznRcvdj5f0zQMHjwYAOo0wMjOzgag71kEgGHDhtW7nnNd53q+wELKhBr6gd+rF+Dc67tjByD87Pot/kcpw9xkmJscs5NhbjLMrRV17AgkJACe7n1RFP15zWxU4A1hYWF48cUXsWDBAkydOtVn79scw4cPR5cuXfDSSy+5HYL32WefYd++fZgyZQoA4MyZM3W6UCYkJCA8PNz1vIKCgjpF3JAhQwDA7bWb2/781KlT9a7z6quvusbudObMGezfvx8nT550LTt58mS9RWV9z3ceblmzoYeqqnjjjTcQHR3tKqD69++PwYMHY+3atW7vtXHjRmRlZWHixImNzsmbLNW1j/S9Uunp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",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 在 AdvertiseGen 数据集10K examples上使用 QLoRA 微调 ChatGLM3-6B，观察 Loss 变化情况\n",
    "# 定义全局变量和参数\n",
    "model_name_or_path = 'THUDM/chatglm3-6b'  # 模型ID或本地路径\n",
    "train_data_path = 'HasturOfficial/adgen'    # 训练数据路径\n",
    "eval_data_path = None                     # 验证数据路径，如果没有则设置为None\n",
    "seed = 8                                 # 随机种子\n",
    "max_input_length = 512                    # 输入的最大长度\n",
    "max_output_length = 1536                  # 输出的最大长度\n",
    "lora_rank = 4                             # LoRA秩\n",
    "lora_alpha = 32                           # LoRA alpha值\n",
    "lora_dropout = 0.05                       # LoRA Dropout率\n",
    "resume_from_checkpoint = None             # 如果从checkpoint恢复训练，指定路径\n",
    "prompt_text = ''                          # 所有数据前的指令文本\n",
    "compute_dtype = 'fp32'                    # 计算数据类型（fp32, fp16, bf16）\n",
    "\n",
    "from datasets import load_dataset\n",
    "from datasets import ClassLabel, Sequence\n",
    "import random\n",
    "import pandas as pd\n",
    "from IPython.display import display, HTML\n",
    "import torch\n",
    "from typing import List, Dict, Optional\n",
    "from transformers import AutoTokenizer, AutoModel, BitsAndBytesConfig, TrainingArguments, Trainer\n",
    "from peft import TaskType, LoraConfig, get_peft_model, prepare_model_for_kbit_training\n",
    "from peft.utils import TRANSFORMERS_MODELS_TO_LORA_TARGET_MODULES_MAPPING\n",
    "target_modules = TRANSFORMERS_MODELS_TO_LORA_TARGET_MODULES_MAPPING['chatglm']\n",
    "\n",
    "dataset = load_dataset(train_data_path)\n",
    "print(dataset) # 打印数据集结果\n",
    "dataset[\"train\"] = dataset[\"train\"].select(range(10000)) # 训练集只取10K的数据去训练\n",
    "\n",
    "\n",
    "def show_random_elements(dataset, num_examples=10):\n",
    "    assert num_examples <= len(dataset), \"Can't pick more elements than there are in the dataset.\"\n",
    "    picks = []\n",
    "    for _ in range(num_examples):\n",
    "        pick = random.randint(0, len(dataset)-1)\n",
    "        while pick in picks:\n",
    "            pick = random.randint(0, len(dataset)-1)\n",
    "        picks.append(pick)\n",
    "    \n",
    "    df = pd.DataFrame(dataset[picks])\n",
    "    for column, typ in dataset.features.items():\n",
    "        if isinstance(typ, ClassLabel):\n",
    "            df[column] = df[column].transform(lambda i: typ.names[i])\n",
    "        elif isinstance(typ, Sequence) and isinstance(typ.feature, ClassLabel):\n",
    "            df[column] = df[column].transform(lambda x: [typ.feature.names[i] for i in x])\n",
    "    display(HTML(df.to_html()))\n",
    "\n",
    "\n",
    "show_random_elements(dataset[\"train\"], num_examples=3)\n",
    "\n",
    "\n",
    "\n",
    "# revision='b098244' 版本对应的 ChatGLM3-6B 设置 use_reentrant=False\n",
    "# 最新版本 use_reentrant 被设置为 True，会增加不必要的显存开销\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name_or_path,\n",
    "                                          trust_remote_code=True,\n",
    "                                          use_reentrant=False,  # 推荐设置\n",
    "                                          revision='b098244')\n",
    "\n",
    "# tokenize_func 函数\n",
    "def tokenize_func(example, tokenizer, ignore_label_id=-100):\n",
    "    \"\"\"\n",
    "    对单个数据样本进行tokenize处理。\n",
    "    参数:\n",
    "    example (dict): 包含'content'和'summary'键的字典，代表训练数据的一个样本。\n",
    "    tokenizer (transformers.PreTrainedTokenizer): 用于tokenize文本的tokenizer。\n",
    "    ignore_label_id (int, optional): 在label中用于填充的忽略ID，默认为-100。\n",
    "    返回:\n",
    "    dict: 包含'tokenized_input_ids'和'labels'的字典，用于模型训练。\n",
    "    \"\"\"\n",
    "    # 构建问题文本\n",
    "    question = prompt_text + example['content']\n",
    "    if example.get('input', None) and example['input'].strip():\n",
    "        question += f'\\n{example[\"input\"]}'\n",
    "\n",
    "    # 构建答案文本\n",
    "    answer = example['summary']\n",
    "\n",
    "    # 对问题和答案文本进行tokenize处理 - 使用更基础的方法避免padding问题\n",
    "    # 注意：这里我们直接使用tokenizer的convert_tokens_to_ids方法\n",
    "    q_tokens = tokenizer.tokenize(question)\n",
    "    a_tokens = tokenizer.tokenize(answer)\n",
    "    \n",
    "    # 转换为ID\n",
    "    q_ids = tokenizer.convert_tokens_to_ids(q_tokens)\n",
    "    a_ids = tokenizer.convert_tokens_to_ids(a_tokens)\n",
    "\n",
    "    # 如果tokenize后的长度超过最大长度限制，则进行截断\n",
    "    if len(q_ids) > max_input_length - 2:  # 保留空间给gmask和bos标记\n",
    "        q_ids = q_ids[:max_input_length - 2]\n",
    "    if len(a_ids) > max_output_length - 1:  # 保留空间给eos标记\n",
    "        a_ids = a_ids[:max_output_length - 1]\n",
    "\n",
    "    # 构建模型的输入格式\n",
    "    input_ids = tokenizer.build_inputs_with_special_tokens(q_ids, a_ids)\n",
    "    question_length = len(q_ids) + 2  # 加上gmask和bos标记\n",
    "\n",
    "    # 构建标签，对于问题部分的输入使用ignore_label_id进行填充\n",
    "    labels = [ignore_label_id] * question_length + input_ids[question_length:]\n",
    "\n",
    "    return {'input_ids': input_ids, 'labels': labels}\n",
    "\n",
    "column_names = dataset['train'].column_names\n",
    "tokenized_dataset = dataset['train'].map(\n",
    "    lambda example: tokenize_func(example, tokenizer),\n",
    "    batched=False, \n",
    "    remove_columns=column_names\n",
    ")\n",
    "\n",
    "\n",
    "show_random_elements(tokenized_dataset, num_examples=1)\n",
    "\n",
    "tokenized_dataset = tokenized_dataset.shuffle(seed=seed)\n",
    "tokenized_dataset = tokenized_dataset.flatten_indices()\n",
    "\n",
    "\n",
    "\n",
    "# DataCollatorForChatGLM 类\n",
    "class DataCollatorForChatGLM:\n",
    "    \"\"\"\n",
    "    用于处理批量数据的DataCollator，尤其是在使用 ChatGLM 模型时。\n",
    "\n",
    "    该类负责将多个数据样本（tokenized input）合并为一个批量，并在必要时进行填充(padding)。\n",
    "\n",
    "    属性:\n",
    "    pad_token_id (int): 用于填充(padding)的token ID。\n",
    "    max_length (int): 单个批量数据的最大长度限制。\n",
    "    ignore_label_id (int): 在标签中用于填充的ID。\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, pad_token_id: int, max_length: int = 2048, ignore_label_id: int = -100):\n",
    "        \"\"\"\n",
    "        初始化DataCollator。\n",
    "\n",
    "        参数:\n",
    "        pad_token_id (int): 用于填充(padding)的token ID。\n",
    "        max_length (int): 单个批量数据的最大长度限制。\n",
    "        ignore_label_id (int): 在标签中用于填充的ID，默认为-100。\n",
    "        \"\"\"\n",
    "        self.pad_token_id = pad_token_id\n",
    "        self.ignore_label_id = ignore_label_id\n",
    "        self.max_length = max_length\n",
    "\n",
    "    def __call__(self, batch_data: List[Dict[str, List]]) -> Dict[str, torch.Tensor]:\n",
    "        \"\"\"\n",
    "        处理批量数据。\n",
    "\n",
    "        参数:\n",
    "        batch_data (List[Dict[str, List]]): 包含多个样本的字典列表。\n",
    "\n",
    "        返回:\n",
    "        Dict[str, torch.Tensor]: 包含处理后的批量数据的字典。\n",
    "        \"\"\"\n",
    "        # 计算批量中每个样本的长度\n",
    "        len_list = [len(d['input_ids']) for d in batch_data]\n",
    "        batch_max_len = max(len_list)  # 找到最长的样本长度\n",
    "\n",
    "        input_ids, labels = [], []\n",
    "        for len_of_d, d in sorted(zip(len_list, batch_data), key=lambda x: -x[0]):\n",
    "            pad_len = batch_max_len - len_of_d  # 计算需要填充的长度\n",
    "            # 添加填充，并确保数据长度不超过最大长度限制\n",
    "            ids = d['input_ids'] + [self.pad_token_id] * pad_len\n",
    "            label = d['labels'] + [self.ignore_label_id] * pad_len\n",
    "            if batch_max_len > self.max_length:\n",
    "                ids = ids[:self.max_length]\n",
    "                label = label[:self.max_length]\n",
    "            input_ids.append(torch.LongTensor(ids))\n",
    "            labels.append(torch.LongTensor(label))\n",
    "\n",
    "        # 将处理后的数据堆叠成一个tensor\n",
    "        input_ids = torch.stack(input_ids)\n",
    "        labels = torch.stack(labels)\n",
    "\n",
    "        return {'input_ids': input_ids, 'labels': labels, 'attention_mask': (input_ids != self.pad_token_id).long()}\n",
    "\n",
    "\n",
    "        \n",
    "# 准备数据整理器\n",
    "data_collator = DataCollatorForChatGLM(pad_token_id=tokenizer.pad_token_id)\n",
    "\n",
    "\n",
    "\n",
    "_compute_dtype_map = {\n",
    "    'fp32': torch.float32,\n",
    "    'fp16': torch.float16,\n",
    "    'bf16': torch.bfloat16\n",
    "}\n",
    "\n",
    "# QLoRA 量化配置\n",
    "q_config = BitsAndBytesConfig(load_in_4bit=True,\n",
    "                              bnb_4bit_quant_type='nf4',\n",
    "                              bnb_4bit_use_double_quant=True,\n",
    "                              bnb_4bit_compute_dtype=_compute_dtype_map['bf16'],\n",
    "                              llm_int8_enable_fp32_cpu_offload=True  # 关键参数\n",
    "                             )\n",
    "\n",
    "\n",
    "\n",
    "# revision='b098244' 版本对应的 ChatGLM3-6B 设置 use_reentrant=False\n",
    "# 最新版本 use_reentrant 被设置为 True，会增加不必要的显存开销\n",
    "model = AutoModel.from_pretrained(model_name_or_path,\n",
    "                                  quantization_config=q_config,\n",
    "                                  device_map='auto',\n",
    "                                  use_cache=False,  # 训练时关闭（梯度检查点需要重新计算中间结果，而缓存会阻止这一过程）\n",
    "                                  trust_remote_code=True,\n",
    "                                  revision='b098244',\n",
    "                                  max_memory={0: \"7GiB\"}\n",
    "                                 )\n",
    "\n",
    "# 确保使用新版检查点\n",
    "model.gradient_checkpointing_enable()\n",
    "\n",
    "# 获取当前模型占用的 GPU显存（差值为预留给 PyTorch 的显存）\n",
    "memory_footprint_bytes = model.get_memory_footprint()\n",
    "memory_footprint_mib = memory_footprint_bytes / (1024 ** 2)  # 转换为 MiB\n",
    "print(\"当前模型占用显存（单位为MiB）：\", memory_footprint_mib)\n",
    "\n",
    "print(f\"{memory_footprint_mib:.2f}MiB\")\n",
    "\n",
    "# 修补模型类（关键修复）\n",
    "original_class = model.__class__\n",
    "class PatchedChatGLM(original_class):\n",
    "    def _extract_past_from_model_output(self, output, *args, **kwargs):\n",
    "        # ChatGLM 特定的缓存提取逻辑\n",
    "        if hasattr(output, 'past_key_values'):\n",
    "            return output.past_key_values\n",
    "        return None\n",
    "\n",
    "model.__class__ = PatchedChatGLM\n",
    "\n",
    "# 准备量化（简化版）\n",
    "kbit_model = prepare_model_for_kbit_training(model)\n",
    "\n",
    "lora_config = LoraConfig(\n",
    "    target_modules=target_modules,\n",
    "    r=lora_rank,\n",
    "    lora_alpha=lora_alpha,\n",
    "    lora_dropout=lora_dropout,\n",
    "    bias='none',\n",
    "    inference_mode=False,\n",
    "    task_type=TaskType.CAUSAL_LM\n",
    ")\n",
    "\n",
    "qlora_model = get_peft_model(kbit_model, lora_config)  # 添加Lora\n",
    "\n",
    "qlora_model.print_trainable_parameters()\n",
    "\n",
    "# 定义训练参数（演示用，减少训练时间）\n",
    "training_demo_args = TrainingArguments(\n",
    "    output_dir=f\"models/demo/{model_name_or_path}\",  # 输出目录：保存模型和日志的路径\n",
    "    per_device_train_batch_size=16,                 # 每个GPU的训练batch大小：根据显存调整\n",
    "    gradient_accumulation_steps=4,                  # 梯度累积步数：模拟更大的batch size\n",
    "    learning_rate=1e-3,                             # 初始学习率：常用范围1e-5到1e-3\n",
    "    max_steps=100,                                  # 最大训练步数：控制演示时长\n",
    "    lr_scheduler_type=\"linear\",                     # 学习率调度策略：线性衰减\n",
    "    warmup_ratio=0.1,                               # 预热比例：前10%步数用于学习率预热\n",
    "    logging_steps=10,                               # 每10步记录一次日志\n",
    "    save_strategy=\"steps\",                          # 保存策略：按步数保存\n",
    "    save_steps=20,                                  # 每20步保存一次模型\n",
    "    optim=\"adamw_torch\",                            # 优化器：AdamW with torch实现\n",
    "    fp16=True,                                      # 启用混合精度训练：减少显存占用\n",
    "    report_to=[\"tensorboard\"],                      # 添加：记录指标到TensorBoard\n",
    "    gradient_checkpointing_kwargs={\"use_reentrant\": False},  # 显式设置\n",
    ")\n",
    "\n",
    "# 初始化Trainer\n",
    "trainer = Trainer(\n",
    "    model=qlora_model,                              # 要训练的模型（QLoRA适配后的模型）\n",
    "    args=training_demo_args,                        # 训练参数配置\n",
    "    train_dataset=tokenized_dataset,                # 训练数据集（已tokenize）\n",
    "    data_collator=data_collator                    # 数据整理器：处理padding和batch\n",
    ")\n",
    "\n",
    "assert model.config.use_cache is False, \"use_cache未正确关闭!\"\n",
    "# 开始训练并记录损失\n",
    "print(\"开始训练...\")\n",
    "train_result = trainer.train()                      # 返回的训练结果包含指标数据\n",
    "\n",
    "# 保存训练后的模型\n",
    "trainer.model.save_pretrained(f\"models/demo/{model_name_or_path}\")\n",
    "print(\"模型保存完成！\")\n",
    "\n",
    "# --- 新增：绘制训练损失曲线 ---\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.ticker import MaxNLocator\n",
    "\n",
    "# 从训练记录中提取损失值\n",
    "log_history = trainer.state.log_history\n",
    "train_loss = [log['loss'] for log in log_history if 'loss' in log]\n",
    "steps = [log['step'] for log in log_history if 'loss' in log]\n",
    "\n",
    "# 创建图表\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.plot(steps, train_loss, 'b-', linewidth=2, label='Training Loss')\n",
    "plt.title('Training Loss Curve', fontsize=14)\n",
    "plt.xlabel('Training Steps', fontsize=12)\n",
    "plt.ylabel('Loss', fontsize=12)\n",
    "plt.grid(True, linestyle='--', alpha=0.6)\n",
    "plt.gca().xaxis.set_major_locator(MaxNLocator(integer=True))  # X轴只显示整数值\n",
    "\n",
    "# 标记最低损失点\n",
    "min_loss_idx = train_loss.index(min(train_loss))\n",
    "plt.scatter(steps[min_loss_idx], train_loss[min_loss_idx], \n",
    "            c='red', s=100, label=f'Min Loss: {train_loss[min_loss_idx]:.3f}')\n",
    "plt.legend(fontsize=12)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "fe73361c-9511-42e9-8f8d-3f2d52f9468f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "532828502703445a86f24cefacdc6043",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "ChatGLM3-6B 微调前:\n",
      "连衣裙采用简约圆领设计，修饰颈部线条，凸显优雅气质。撞色印花图案点缀，增添文艺气息，凸显时尚感。压褶裙摆，修饰臀部曲线，显瘦显高。\n",
      "\n",
      "ChatGLM3-6B 微调后:\n",
      "连衣裙采用简约圆领设计，修饰颈部线条，凸显优雅气质。撞色印花图案点缀，增添文艺气息，凸显时尚感。压褶裙摆，修饰臀部曲线，显瘦显高。\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig\n",
    "from peft import PeftModel, PeftConfig\n",
    "\n",
    "# 1. 基础配置\n",
    "model_name_or_path = 'THUDM/chatglm3-6b'\n",
    "peft_model_path = 'models/demo/THUDM/chatglm3-6b'\n",
    "compute_dtype = torch.bfloat16\n",
    "\n",
    "# 2. 量化配置\n",
    "q_config = BitsAndBytesConfig(\n",
    "    load_in_4bit=True,\n",
    "    bnb_4bit_quant_type=\"nf4\",\n",
    "    bnb_4bit_use_double_quant=True,\n",
    "    bnb_4bit_compute_dtype=compute_dtype,\n",
    ")\n",
    "\n",
    "# 3. 加载基础模型\n",
    "base_model = AutoModelForCausalLM.from_pretrained(\n",
    "    model_name_or_path,\n",
    "    quantization_config=q_config,\n",
    "    trust_remote_code=True,\n",
    "    device_map=\"auto\",\n",
    "    use_cache=True,\n",
    "    torch_dtype=compute_dtype,\n",
    "    revision='b098244'\n",
    ")\n",
    "base_model.requires_grad_(False)\n",
    "base_model.eval()\n",
    "\n",
    "# 4. 加载tokenizer但不使用其预处理功能\n",
    "tokenizer = AutoTokenizer.from_pretrained(\n",
    "    model_name_or_path,\n",
    "    trust_remote_code=True,\n",
    "    revision='b098244'\n",
    ")\n",
    "\n",
    "# 手动设置关键token ID（ChatGLM3-6B特定值）\n",
    "BOS_TOKEN_ID = 64792  # sop\n",
    "EOS_TOKEN_ID = 2      # </s>\n",
    "PAD_TOKEN_ID = 0      # <unk>\n",
    "\n",
    "# 5. 加载LoRA适配器\n",
    "peft_config = PeftConfig.from_pretrained(peft_model_path)\n",
    "peft_config.inference_mode = True\n",
    "\n",
    "model = PeftModel.from_pretrained(\n",
    "    base_model,\n",
    "    peft_model_path,\n",
    "    config=peft_config,\n",
    "    torch_dtype=compute_dtype\n",
    ")\n",
    "model.eval()\n",
    "\n",
    "# 6. 完全手动实现的生成函数\n",
    "def generate_text(curModel, input_text, max_new_tokens=100):\n",
    "    \"\"\"完全绕过tokenizer预处理的生成函数\"\"\"\n",
    "    try:\n",
    "        # 步骤1：手动tokenization\n",
    "        tokens = tokenizer.tokenize(input_text)\n",
    "        \n",
    "        # 步骤2：转换为token IDs\n",
    "        input_ids = tokenizer.convert_tokens_to_ids(tokens)\n",
    "        \n",
    "        # 步骤3：添加特殊token\n",
    "        input_ids = [BOS_TOKEN_ID] + input_ids + [EOS_TOKEN_ID]\n",
    "        \n",
    "        # 步骤4：创建并准备输入tensor\n",
    "        input_tensor = torch.tensor([input_ids], dtype=torch.long, device=model.device)\n",
    "        # print(\"input_tensor-size: \", input_tensor.shape)\n",
    "        \n",
    "        # 步骤5：生成（手动实现生成逻辑）\n",
    "        generated_tokens = []\n",
    "        with torch.no_grad():\n",
    "            for _ in range(max_new_tokens):\n",
    "                outputs = curModel(input_ids=input_tensor)\n",
    "                next_token_logits = outputs.logits[:, -1, :]\n",
    "                next_token = torch.argmax(next_token_logits, dim=-1)\n",
    "                generated_tokens.append(next_token.item())\n",
    "                \n",
    "                # 修正维度不匹配问题\n",
    "                next_token = next_token.unsqueeze(0)  # 添加batch维度\n",
    "                input_tensor = torch.cat([input_tensor, next_token], dim=1)\n",
    "                \n",
    "                # print(\"当前input_tensor-size: \", input_tensor.shape)\n",
    "                if next_token.item() == EOS_TOKEN_ID:\n",
    "                    break\n",
    "        \n",
    "        # 步骤6：解码结果（跳过特殊token）\n",
    "        generated_text = tokenizer.decode(generated_tokens, skip_special_tokens=True)\n",
    "        return generated_text\n",
    "    except Exception as e:\n",
    "        print(f\"生成失败: {str(e)}\")\n",
    "        return \"\"\n",
    "\n",
    "# 7. 测试\n",
    "if __name__ == \"__main__\":\n",
    "    test_input = \"类型#裙*版型#显瘦*风格#文艺*风格#简约*图案#印花*图案#撞色*裙下摆#压褶*裙长#连衣裙*裙领型#圆领\"\n",
    "    \n",
    "    # print(\"=== 生成测试 ===\")\n",
    "    # print(\"关键token ID检查:\")\n",
    "    # print(f\"BOS: {BOS_TOKEN_ID}\")\n",
    "    # print(f\"EOS: {EOS_TOKEN_ID}\")\n",
    "    # print(f\"PAD: {PAD_TOKEN_ID}\")\n",
    "\n",
    "    result = generate_text(base_model, test_input)\n",
    "    print(\"\\nChatGLM3-6B 微调前:\")\n",
    "    print(result)\n",
    "    \n",
    "    result = generate_text(model, test_input)\n",
    "    print(\"\\nChatGLM3-6B 微调后:\")\n",
    "    print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "220ec0c7-fad5-4783-b9b8-f59dfb37732c",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
